import wormbane.action as action
from wormbane.action import ActionError
from wormbane.direction import (direction_to_planar_vector,
                                is_horizontal_direction, is_vertical_direction)
from wormbane.Feature import Door, Stair
from wormbane.geometry import Vector
import random


def handle_command(command, game):
    try:
        if is_horizontal_direction(command):
            do_move(command, game)
        elif is_vertical_direction(command):
            do_climb(command, game)
        elif command == 'close':
            do_close(game)
        elif command == 'open':
            do_open(game)
        elif command == 'rest':
            do_rest(game)
        elif command == 'search':
            do_search(game)
    except ActionError:
        pass


def do_climb(command, game):
    feature = game.hero.tile.feature
    if type(feature) is not Stair or feature.dir != command:
        game.write('You cannot go %s here.' % command)
        return
    if game.current_level.num == 1 and command == 'up':
        if not game.hero.is_nemesis_nemesis:
            game.write('You cannot leave the dungeon yet.')
            return
        else:
            game.completed = True
            return
    game.change_level(game.current_level.num
                      + (1 if command == 'down' else -1))


def do_close(game):
    doors = [tile.feature for tile in game.hero.env.neighbors
             if type(tile.feature) is Door and not tile.feature.closed
             and not tile.monster and not tile.top_item]
    if doors:
        action.do_close_door(game.hero, random.choice(doors), game)
    else:
        game.write('There is nothing to close here.')


def do_move(command, game):
    x, y = Vector(game.hero.pos) + direction_to_planar_vector(command)
    if (x, y) in game.current_level.bounds:
        tile = game.current_level.tiles[x][y]
        if tile.monster:
            action.do_hit_monster(game.hero, tile.monster, game)
        elif tile.top_item and not tile.top_item.passable:
            action.do_push_boulder(game.hero, tile.top_item, game)
        elif type(tile.feature) is Door and tile.feature.closed:
            action.do_kick_door(game.hero, tile.feature, game)
        else:
            action.do_move(game.hero, tile, game)


def do_open(game):
    doors = [tile.feature for tile in game.hero.env.neighbors
             if type(tile.feature) is Door and tile.feature.closed]
    if doors:
        door = random.choice(doors)
        if door.locked:
            game.write('The door is locked.')
        else:
            action.do_open_door(game.hero, door, game)
    else:
        game.write('There is nothing to open here.')


def do_rest(game):
    action.do_rest(game.hero, game)


def do_search(game):
    action.do_search(game.hero, game)
